package com.atguigu.lease.admin.service.impl;

import com.atguigu.lease.admin.mapper.ApartmentFacilityMapper;
import com.atguigu.lease.admin.mapper.ApartmentFeeValueMapper;
import com.atguigu.lease.admin.mapper.ApartmentLabelMapper;
import com.atguigu.lease.admin.service.*;
import com.atguigu.lease.admin.service.*;
import com.atguigu.lease.model.bean.*;
import com.atguigu.lease.model.enums.ItemTypeEnum;
import com.atguigu.lease.model.vo.*;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.lease.admin.mapper.ApartmentInfoMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author LOGIN
* @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
* @createDate 2025-06-21 01:15:32
*/
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
    implements ApartmentInfoService {

    @Autowired
    private ProvinceInfoService provinceInfoService;
    @Autowired
    private CityInfoService cityInfoService;
    @Autowired
    private DistrictInfoService districtInfoService;
    @Autowired
    private ApartmentFacilityService apartmentFacilityService;
    @Autowired
    private ApartmentLabelService apartmentLabelService;
    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;
    @Autowired
    private GraphInfoService graphInfoService;
    @Autowired
    private ApartmentFacilityMapper apartmentFacilityMapper;
    @Autowired
    private ApartmentLabelMapper apartmentLabelMapper;
    @Autowired
    private ApartmentFeeValueMapper apartmentFeeValueMapper;


    @Override
    public void saveOrUpdateApartmentSubmitVo(ApartmentSubmitVo apartmentSubmitVo) {
        // 1、 先保存或更新公寓 ： 得到公寓的id
        // 更新前端会提交公寓的id
        boolean isUpdate = apartmentSubmitVo.getId() !=null;
        //前端未提交省市区名称
        ProvinceInfo provinceInfo = provinceInfoService.getById(apartmentSubmitVo.getProvinceId());
        CityInfo cityInfo = cityInfoService.getById(apartmentSubmitVo.getCityId());
        DistrictInfo districtInfo =districtInfoService.getById(apartmentSubmitVo.getDistrictId());
        apartmentSubmitVo.setProvinceName(provinceInfo.getName());
        apartmentSubmitVo.setCityName(cityInfo.getName());
        apartmentSubmitVo.setDistrictName(districtInfo.getName());
        //调用mp的通用service 保存或更新 公寓表中的数据
        this.saveOrUpdate(apartmentSubmitVo);

        Long id = apartmentSubmitVo.getId();
        //2、在保存或更新公寓的其他信息：使用 公寓的id关联其他信息
        //如果新增公寓，所有的配套、标签等数据等都是第一次添加
        //如果更新公寓， 有些配套、标签新增的，而有些是存在的，，还有一些没有传入 但是数据库还保存着
        //                    可以先删除所有的配套标签数据，然后将更新的配套 标签 等数据新增到列表中
        //todo 2.1 、 更新先删除其他信息
        if(isUpdate){
        //配套： 使用公寓id删除公寓的所有
            apartmentFacilityService.remove(Wrappers.lambdaQuery(ApartmentFacility.class)
                    .eq(ApartmentFacility::getApartmentId,id));
        //标签
            apartmentLabelService.remove(Wrappers.lambdaQuery(ApartmentLabel.class)
                    .eq(ApartmentLabel::getApartmentId,id));
        //杂费值
            apartmentFeeValueService.remove(Wrappers.lambdaQuery(ApartmentFeeValue.class)
                    .eq(ApartmentFeeValue::getApartmentId,id));
        //图片：图片可能包含了公寓和房间的图片 （公寓表和房间表的id都是用了自增长，所以id可能重复）
            // item_id=公寓id and item_type=1(公寓类型)
            graphInfoService.remove(Wrappers.lambdaQuery(GraphInfo.class)
                    .eq(GraphInfo::getId,id)
                    .eq(GraphInfo::getItemType, ItemTypeEnum.APARTMENT));
        }
        //2.2 新增或更新：保存公寓的其他信息
        //配套信息
        List<Long> facilityInfoIds = apartmentSubmitVo.getFacilityInfoIds();
        //公寓配套集合
        List<ApartmentFacility> apartmentFacilities =new ArrayList<>();
        facilityInfoIds.forEach(facilityInfoId->{
            //公寓配套对象，由公寓id和配套id组成
            ApartmentFacility apartmentFacility = new ApartmentFacility();
            apartmentFacility.setApartmentId(id);
            apartmentFacility.setFacilityId(facilityInfoId);
            //遍历创建的一个公寓配套对象，存到集合中
            apartmentFacilities.add(apartmentFacility);
        });
        //批量保存公寓配套对象集合
        apartmentFacilityService.saveBatch(apartmentFacilities);
        //标签信息
        List<ApartmentLabel> apartmentLabels = apartmentSubmitVo.getLabelIds().stream()
                //streamAPI map()可以将流中的每个元素转为其他类型的对象
                .map(labelId -> {
                    ApartmentLabel apartmentLabel = new ApartmentLabel();
                    //设置公寓id
                    apartmentLabel.setApartmentId(id);
                    //设置公寓选择的标签id
                    apartmentLabel.setLabelId(labelId);
                    return apartmentLabel;
                })
                //将前面的流数据转为对象 存到List集合中
                .collect(Collectors.toList());
        //批量保存
            apartmentLabelService.saveBatch(apartmentLabels);

        //杂费信息
        //将杂费值id列表转为  公寓杂费值对象集合
        List<ApartmentFeeValue> apartmentFeeValues = apartmentSubmitVo.getFeeValueIds().stream()
                .map(feeValueId -> {
                    ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                    apartmentFeeValue.setApartmentId(id);
                    apartmentFeeValue.setFeeValueId(feeValueId);
                    return apartmentFeeValue;
                })
                .collect(Collectors.toList());

        //批量保存
            apartmentFeeValueService.saveBatch(apartmentFeeValues);

            //图片
        //将接收到的图片集合 转为数据库表映射的实体类对象集合（还需要绑定公寓+设置图片类型）
        List<GraphInfo> graphInfos = apartmentSubmitVo.getGraphVoList().stream()
                .map(graphVo -> {
                    GraphInfo graphInfo = new GraphInfo();
                    graphInfo.setUrl(graphVo.getUrl());
                    graphInfo.setName(graphVo.getName());
                    //设置图片属于哪个公寓
                    graphInfo.setItemId(id);
                    //设置图片类型 ： 1- 公寓 2- 房间
                    graphInfo.setItemType(ItemTypeEnum.APARTMENT.getCode());
                    return graphInfo;
                }).collect(Collectors.toList());

        graphInfoService.saveBatch(graphInfos);
    }

    @Override
    public Page<ApartmentItemVo> getPageItem(Long current, Long size, ApartmentQueryVo queryVo) {
        //mp 自定义分页：
        //1、配置分页拦截器   2、传入page对象携带分页的页码和size  3、传入自定义条件 手动给洗在sql中使用

        return baseMapper.selectApartmentItemVoPage(new Page<>(current,size),queryVo);
    }

    @Override
    public ApartmentDetailVo getDetailById(Long id) {
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        //查询公寓数据
        ApartmentInfo apartmentInfo = this.getById(id);
        // 设置公寓属性值给VO
        //BeanUtils 是sprig的工具类 ，可以将一个对象的属性值拷贝给另一个对象相同类型相同名称的属性
        BeanUtils.copyProperties(apartmentInfo,apartmentDetailVo);//尽量早复制！
        //2、设置其他数据据给VO
        //2、1 查询公寓的配套数据： 需要通过中间表联查（apartment_facility、  facility_info表）
        List<FacilityInfo> facilityInfos =apartmentFacilityMapper.selectfacilityInfoByApartmentId(id);
        //设置配套列表给VO
        apartmentDetailVo.setFacilityInfoList(facilityInfos);

        //2.2 查询公寓的标签信息
        List<LabelInfo> labelInfos= apartmentLabelMapper.selectApartmentLabelByApartmentId(id);
        //设置标签列表给VO
        apartmentDetailVo.setLabelInfoList(labelInfos);
        //2.3 查询公寓的杂费信息
        List<FeeValueVo> feeValueVos= apartmentFeeValueMapper.selectApartmentFeeValueBylByApartmentId(id);
        apartmentDetailVo.setFeeValueVoList(feeValueVos);
        //2.4 查询公寓图片数据
        // graph_info表： 使用了item_id关联id
        //使用公寓id+图片 所属类型 查询公寓的图片列表
        List<GraphVo> graphVoList = graphInfoService.list(Wrappers.lambdaQuery(GraphInfo.class)
                        .eq(GraphInfo::getItemId, id)
                        .eq(GraphInfo::getItemType, ItemTypeEnum.APARTMENT))
                .stream()
                .map(graphInfo -> {
                    GraphVo graphVo = new GraphVo();
                    BeanUtils.copyProperties(graphInfo, graphVo);
                    return graphVo;
                }).collect(Collectors.toList());
        apartmentDetailVo.setGraphVoList(graphVoList);

//      最终，将组装好数据的VO对象返回
        return apartmentDetailVo;
    }

    @Transactional(rollbackFor = Exception.class) //启用声明式事务
    @Override
    public void deleteApartmentById(Long id) {
        //1、删除公寓数据
        this.removeById(id);
        //2、 删除公寓配套信息
        apartmentFacilityService.remove(Wrappers.lambdaQuery(ApartmentFacility.class)
                .eq(ApartmentFacility::getApartmentId, id));
        //3、 删除公寓标签数据
        apartmentLabelService.remove(Wrappers.lambdaQuery(ApartmentLabel.class)
                .eq(ApartmentLabel::getApartmentId,id));
        //4、 删除公寓杂费值数据
        apartmentFeeValueService.remove(Wrappers.lambdaQuery(ApartmentFeeValue.class)
                .eq(ApartmentFeeValue::getApartmentId,id));
        //5、 删除公寓图片数据
        graphInfoService.remove(Wrappers.lambdaQuery(GraphInfo.class)
                .eq(GraphInfo::getItemId,id)
                .eq(GraphInfo::getItemType,ItemTypeEnum.APARTMENT));
    }
}




